﻿
namespace VS2048
{
    /// <summary>
    /// 通过方向键来控制合并Cell的策略
    /// </summary>
    public class DirectionCellMergeStrategy : ICellMergeStrategy
    {
        CellStyleDictionary _csd = new CellStyleDictionary();
        /// <summary>
        /// 返回当前合并得分
        /// </summary>
        /// <param name="keyVal"></param>
        /// <param name="celltable"></param>
        /// <returns></returns>
        public int Merge(int keyVal, ICell[,] celltable)
        {
            int score = 0;
            switch (keyVal)
            {
                case 37:
                    AlignLeft(celltable);
                    score = MergeLeft(celltable);
                    AlignLeft(celltable);
                    break;
                case 38:
                    AlignTop(celltable);
                    score = MergeTop(celltable);
                    AlignTop(celltable);
                    break;
                case 39:
                    AlignRight(celltable);
                    score = MergeRight(celltable);
                    AlignRight(celltable);
                    break;
                case 40:
                    AlignBottom(celltable);
                    score = MergeBottom(celltable);
                    AlignBottom(celltable);
                    break;
            }
            return score;
        }
        //<-
        private int MergeLeft(ICell[,] celltable)
        {
            int score = 0;
            if (celltable != null)
            {
                for (int i = 0; i < celltable.GetLength(0); i++)
                {
                    for (int j = 0; j < celltable.GetLength(1) - 1; j++)
                    {
                        if ((celltable[i, j] == null) || (celltable[i, j + 1] == null)) continue;
                        if (celltable[i, j].DisplayNum == celltable[i, j + 1].DisplayNum)
                        {
                            int num = int.Parse(celltable[i, j].DisplayNum) * 2;
                            celltable[i, j].DisplayNum = num.ToString();
                            celltable[i, j].BackColor = _csd[num].BackColor;
                            celltable[i, j].TextColor = _csd[num].TextColor;
                            celltable[i, j].TextFont = _csd[num].TextFont;

                            celltable[i, j + 1] = null;

                            score += num;
                        }
                    }
                }
            }
            return score;
        }
        //->
        private int MergeRight(ICell[,] celltable)
        {
            int score = 0;
            if (celltable != null)
            {
                for (int i = 0; i < celltable.GetLength(0); i++)
                {
                    for (int j = celltable.GetLength(1) - 1; j >= 1; j--)
                    {
                        if ((celltable[i, j] == null) || (celltable[i, j - 1] == null)) continue;
                        if (celltable[i, j].DisplayNum == celltable[i, j - 1].DisplayNum)
                        {
                            int num = int.Parse(celltable[i, j].DisplayNum) * 2;
                            celltable[i, j].DisplayNum = num.ToString();
                            celltable[i, j].BackColor = _csd[num].BackColor;
                            celltable[i, j].TextColor = _csd[num].TextColor;
                            celltable[i, j].TextFont = _csd[num].TextFont;

                            celltable[i, j - 1] = null;
                            score += num;
                        }
                    }
                }
            }
            return score;
        }
        //^
        private int MergeTop(ICell[,] celltable)
        {
            int score = 0;
            if (celltable != null)
            {
                for (int j = 0; j < celltable.GetLength(1); j++)
                {
                    for (int i = 0; i < celltable.GetLength(0) - 1; i++)
                    {
                        if ((celltable[i, j] == null) || (celltable[i + 1, j] == null)) continue;
                        if (celltable[i, j].DisplayNum == celltable[i + 1, j].DisplayNum)
                        {
                            int num = int.Parse(celltable[i, j].DisplayNum) * 2;
                            celltable[i, j].DisplayNum = num.ToString();
                            celltable[i, j].BackColor = _csd[num].BackColor;
                            celltable[i, j].TextColor = _csd[num].TextColor;
                            celltable[i, j].TextFont = _csd[num].TextFont;

                            celltable[i + 1, j] = null;
                            score += num;
                        }
                    }
                }
            }
            return score;
        }
        //~
        private int MergeBottom(ICell[,] celltable)
        {
            int score = 0;
            if (celltable != null)
            {
                for (int j = 0; j < celltable.GetLength(1); j++)
                {
                    for (int i = celltable.GetLength(0) - 1; i >= 1; i--)
                    {
                        if ((celltable[i, j] == null) || (celltable[i - 1, j] == null)) continue;
                        if (celltable[i, j].DisplayNum == celltable[i - 1, j].DisplayNum)
                        {
                            int num = int.Parse(celltable[i, j].DisplayNum) * 2;
                            celltable[i, j].DisplayNum = num.ToString();
                            celltable[i, j].BackColor = _csd[num].BackColor;
                            celltable[i, j].TextColor = _csd[num].TextColor;
                            celltable[i, j].TextFont = _csd[num].TextFont;

                            celltable[i - 1, j] = null;
                            score += num;
                        }
                    }
                }
            }
            return score;
        }
        /// <summary>
        /// 先不合并，而是把所有的Cell往左对齐，之间没有空白
        /// </summary>
        /// <param name="celltable"></param>
        private void AlignLeft(ICell[,] celltable)
        {
            if (celltable != null)
            {
                int rowlen = celltable.GetLength(0);
                int collen = celltable.GetLength(1);

                for (int i = 0; i < rowlen; i++)
                {
                    int idx = 0;
                    ICell[] tcell = new ICell[collen];
                    for (int j = 0; j < collen; j++)
                    {
                        if (celltable[i, j] == null) continue;

                        tcell[idx] = celltable[i, j];
                        tcell[idx].Left -= tcell[idx].ParentWidth * (j - idx);
                        ++idx;
                    }
                    for (int j = 0; j < collen; j++)
                    {
                        celltable[i, j] = tcell[j];
                    }
                }
            }
        }
        /// <summary>
        /// 右对齐Cell
        /// </summary>
        /// <param name="celltable"></param>
        private void AlignRight(ICell[,] celltable)
        {
            if (celltable != null)
            {
                int rowlen = celltable.GetLength(0);
                int collen = celltable.GetLength(1);

                for (int i = 0; i < rowlen; i++)
                {
                    int idx = collen - 1;
                    ICell[] tcell = new ICell[collen];
                    for (int j = collen - 1; j >= 0; j--)
                    {
                        if (celltable[i, j] == null) continue;

                        tcell[idx] = celltable[i, j];
                        tcell[idx].Left += tcell[idx].ParentWidth * (idx - j);
                        --idx;
                    }
                    for (int j = 0; j < collen; j++)
                    {
                        celltable[i, j] = tcell[j];
                    }
                }
            }
        }
        /// <summary>
        /// 需要注意的是控件的坐标系是左上角为00原点，x向右、y向下为正增长
        /// </summary>
        /// <param name="celltable"></param>
        private void AlignTop(ICell[,] celltable)
        {
            if (celltable != null)
            {
                int rowlen = celltable.GetLength(0);
                int collen = celltable.GetLength(1);

                for (int j = 0; j < collen; j++)
                {
                    int idx = 0;
                    ICell[] tcell = new ICell[rowlen];
                    for (int i = 0; i < rowlen; i++)
                    {
                        if (celltable[i, j] == null) continue;

                        tcell[idx] = celltable[i, j];
                        tcell[idx].Top -= tcell[idx].ParentWidth * (i - idx);
                        ++idx;
                    }
                    for (int i = 0; i < rowlen; i++)
                    {
                        celltable[i, j] = tcell[i];
                    }
                }
            }
        }

        private void AlignBottom(ICell[,] celltable)
        {
            if (celltable != null)
            {
                int rowlen = celltable.GetLength(0);
                int collen = celltable.GetLength(1);

                for (int j = 0; j < collen; j++)
                {
                    int idx = rowlen - 1;
                    ICell[] tcell = new ICell[rowlen];
                    for (int i = rowlen - 1; i >= 0; i--)
                    {
                        if (celltable[i, j] == null) continue;

                        tcell[idx] = celltable[i, j];
                        tcell[idx].Top += tcell[idx].ParentWidth * (idx - i);
                        --idx;
                    }
                    for (int i = 0; i < rowlen; i++)
                    {
                        celltable[i, j] = tcell[i];
                    }
                }
            }
        }
    }
}
